using System;
using System.Collections.Generic;
using System.Text;
using T.FAS.Runtime.Action.SPI;
using T.FAS.Runtime.Base.Entity;

namespace T.FAS.Runtime.Action.Engine
{
    abstract class AbsActionExecuteEngine: IActionExecuteEngine
    {
        protected ActionExecuteEngineConfig config;

        protected IActionExecuteHandler executeHandler;

        public IActionExecuteEngine SubEngine { get; set; }

        public abstract TResult Execute(ActionExecContext context);

        protected TResult LocalInvoke(ActionExecContext context)
        {

            //编排控制

            TResult dataResult = null;
            DateTime startTime = DateTime.Now;
            Exception ex =null;
            var proxyName = "";

            try
            {
                var proxy = ActionRunTimeEngineFactory.Create(context);

                proxyName = proxy.GetType().Name;

                InitActionExecuteHandler(proxy);

                BeforeExecute(context);

                var result = proxy.Execute(context);

                if (this.SubEngine != null)
                {
                    var subResults = proxy.ExecuteWithSubEngine(this.SubEngine,context);
                }

                dataResult = ConstructActionDataResult(proxy, context, result);

                AfterExecute(context, dataResult);

                return dataResult;
            }
            catch (Exception e)
            {
                ex = e;
                var errCode = ActionExecuteExceptionCode.ActionExecuteEngineExecuteError;
                if (ex is FasException)
                {
                    errCode = (ex as FasException).Code;
                }
                throw new FasException(errCode, ex.Message, ex);
                //fix:删除了注释代码 2024.3.28
            }
            finally
            {
                ActionEngineMonitor.MonitorActionEngineTotalTPS(context,proxyName);
                if (ex == null)
                {
                    ActionEngineMonitor.MonitorActionEngineSuccessTPS(context, proxyName);
                    ActionEngineMonitor.MonitorActionEngineSuccessDuration(context, proxyName,(DateTime.Now - startTime).TotalMilliseconds);
                }
                else
                {
                    ActionEngineMonitor.MonitorActionEngineFailTPS(context,proxyName);
                }
            }

            return dataResult;
        }
        protected TResult RemoteInvoke(ActionExecContext context)
        {
            return new RemoteInvokeEngine().Execute(context) as TResult;
        }

        protected void AfterExecute(ActionExecContext context, TResult dataResult)
        {
            if (executeHandler == null) return;

            executeHandler.AfterExecute(context);
        }

        protected TResult ConstructActionDataResult(IActionExecuteProxy proxy, ActionExecContext context, object result)
        {
            var builder = proxy as IActionDataResultBuilder;

            return builder.BuildActionDataResult(context, result);
        }

        protected void OnActioExecuteError(ActionExecContext context, Exception ex)
        {
            if (executeHandler == null) return;

            executeHandler.ExecuteError(context, ex);
        }

        protected void BeforeExecute(ActionExecContext context)
        {
            if (executeHandler == null) return;

            executeHandler.BeforeExecute(context);
        }

        protected void InitActionExecuteHandler(IActionExecuteProxy actionExecuteProxy)
        {
            if (config.ActionExecuteStrategy == ActionExecuteStrategy.DefaultIntercept)
            {
                executeHandler = actionExecuteProxy as IActionExecuteHandler;
            }
        }

        protected void GetDefaultConfig()
        {
            config = new ActionExecuteEngineConfig();
        }
    }
}
